package user

import (
	"context"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/moneyx"
	"mall/common/resultx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetUserInfoLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic {
	return &GetUserInfoLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *GetUserInfoLogic) GetUserInfo(in *user.CurrentUserReq) (*user.CurrentUserInfo, error) {
	if in.UserId == nil || *in.UserId == 0 {
		return nil, resultx.StatusError(resultx.USER_ID_REQUIRED, "")
	}

	if in.AuthType == nil || len(strings.TrimSpace(*in.AuthType)) == 0 {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	res, err := l.svcCtx.CurrentUser.FindOne(l.ctx, *in.UserId)
	if err != nil {
		return nil, err
	}

	userProfile := &user.UserProfileInfo{
		Id:     pointy.GetPointer(res.ID),
		Mobile: pointy.GetPointer(res.UserMobile),
		Email:  pointy.GetPointer(res.UserEmail),
		Name:   pointy.GetPointer(res.UserLogin),
	}
	var userAccount *user.UserAccountInfo
	var userTaskStatisticMap map[string]uint32

	switch strings.TrimSpace(*in.AuthType) { // Todo:
	case globalkey.UserAuthTypeWechatMini:
		uid := res.ID
		authFilterMap := make(map[string]map[string][]any)
		authFilterMap[model.UserAuthColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		authFilterMap[model.UserAuthColumns.PlatformID] = map[string][]any{
			"equalTo": []any{globalkey.ThirdPartyPlatformWechatMini},
		}
		authList, _, err := l.svcCtx.CurrentUser.GetAuthList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, authFilterMap)
		if err != nil || len(authList) == 0 {
			return nil, err
		}

		userAuth := authList[0]
		userProfile.Nickname = pointy.GetPointer(userAuth.Nickname)
		userProfile.Avatar = pointy.GetPointer(userAuth.Avatar)
		userProfile.Gender = pointy.GetPointer(uint32(userAuth.Gender))
		userProfile.Birthday = pointy.GetPointer(modelx.FormatNullDotTime(userAuth.Birthday, "2006-01-02"))

		accountFilterMap := make(map[string]map[string][]any)
		accountFilterMap[model.UserAccountColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		accountList, _, err := l.svcCtx.CurrentUser.GetAccountList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, accountFilterMap)
		if err != nil || len(accountList) == 0 {
			return nil, err
		}

		account := accountList[0]
		var availablePoint uint64
		if account.Point > 0 {
			availablePoint = uint64(account.Point)
			if availablePoint > account.FrozenPoint {
				availablePoint -= account.FrozenPoint
			} else {
				availablePoint = 0
			}
		}
		var availableBalance uint64
		if account.Balance > 0 {
			availableBalance = uint64(account.Balance)
			if availableBalance > account.FrozenBalance {
				availableBalance -= account.FrozenBalance
			} else {
				availableBalance = 0
			}
		}
		userAccount = &user.UserAccountInfo{
			Point:            pointy.GetPointer(account.Point),
			FrozenPoint:      pointy.GetPointer(account.FrozenPoint),
			AvailablePoint:   pointy.GetPointer(availablePoint),
			HistoryPoint:     pointy.GetPointer(account.HistoryPoint),
			Balance:          pointy.GetPointer(moneyx.FormatGem(account.Balance)),
			FrozenBalance:    pointy.GetPointer(moneyx.FormatGem(int64(account.FrozenBalance))),
			AvailableBalance: pointy.GetPointer(moneyx.FormatGem(int64(availableBalance))),
			Loan:             pointy.GetPointer(account.Loan),
			Credit:           pointy.GetPointer(account.Credit),
			Level:            pointy.GetPointer(uint32(account.Level)),
		}
		userProfile.Level = pointy.GetPointer(uint32(account.Level))

		statisticFilterMap := make(map[string]map[string][]any)
		statisticFilterMap[model.UserTaskLogColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		statisticFilterMap[model.UserTaskLogColumns.Status] = map[string][]any{
			"equalTo": []any{globalkey.StatusEnabled},
		}
		statisticList, _, err := l.svcCtx.CurrentUser.GetTaskLogList(l.ctx, model.M{
			"statistic": "1",
		}, -1, statisticFilterMap)
		if err != nil {
			return nil, err
		}

		if len(statisticList) > 0 {
			userTaskStatisticMap = make(map[string]uint32)
			for _, v := range statisticList {
				userTaskStatisticMap[v.TaskSlug] = uint32(v.Growth)
			}
		}

		metaFilterMap := make(map[string]map[string][]any)
		metaFilterMap[model.UserMetumColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		metaFilterMap[model.UserMetumColumns.MetaKey] = map[string][]any{
			"equalTo": []any{"_birthday_hidden"},
		}
		metaList, _, err := l.svcCtx.CurrentUser.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
		if err != nil {
			return nil, err
		}

		if len(metaList) > 0 {
			for _, m := range metaList {
				if m.MetaKey != "" && m.MetaValue.Valid {
					if m.MetaKey == "_birthday_hidden" && m.MetaValue.String == "1" {
						userProfile.BirthdayHidden = pointy.GetPointer(uint32(1))
					}
				}
			}
		}
	}

	l.svcCtx.CurrentUser.UpdateMetum(l.ctx, nil, &model.UserMetum{
		UserID:    res.ID,
		MetaKey:   "_last_activity",
		MetaValue: null.StringFrom(strconv.FormatInt(time.Now().Unix(), 10)),
	})

	return &user.CurrentUserInfo{
		UserProfile:          userProfile,
		UserAccount:          userAccount,
		UserTaskStatisticMap: userTaskStatisticMap,
	}, nil
}
